package com.ruoyi.system.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ijpay.core.IJPayHttpResponse;
import com.ijpay.core.enums.RequestMethod;
import com.ijpay.core.kit.PayKit;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.core.utils.DateTimeZoneUtil;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.enums.WxDomainEnum;
import com.ijpay.wxpay.enums.v3.BasePayApiEnum;
import com.ijpay.wxpay.model.v3.Amount;
import com.ijpay.wxpay.model.v3.UnifiedOrderModel;
import com.ruoyi.common.config.WxPayV3Config;
import com.ruoyi.common.constant.GenConstants;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.ProductOrder;
import com.ruoyi.system.domain.ProductPrice;
import com.ruoyi.system.domain.ProductType;
import com.ruoyi.system.service.IProductOrderService;
import com.ruoyi.system.service.IProductPriceService;
import com.ruoyi.system.service.IProductTypeService;
import com.ruoyi.system.service.IWxPayV3Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.security.cert.X509Certificate;

@Service
public class WxPayV3ServiceImpl  implements IWxPayV3Service {

    private static final Logger log = LoggerFactory.getLogger(WxPayV3ServiceImpl.class);
    @Autowired
    private WxPayV3Config wxPayV3Bean;

    @Autowired
    private IProductTypeService productTypeService;

    @Autowired
    private IProductPriceService productPriceService;

    @Autowired
    private IProductOrderService productOrderService;


    String serialNo;
    String platSerialNo;
    private String getSerialNumber() {
        if (StrUtil.isEmpty(serialNo)) {
            // 获取证书序列号
            X509Certificate certificate = PayKit.getCertificate(wxPayV3Bean.getCertPath());
            if (null != certificate) {
                serialNo = certificate.getSerialNumber().toString(16).toUpperCase();
                // 提前两天检查证书是否有效
                boolean isValid = PayKit.checkCertificateIsValid(certificate, wxPayV3Bean.getMchId(), -2);
                log.info("证书是否可用 {} 证书有效期为 {}", isValid, DateUtil.format(certificate.getNotAfter(), DatePattern.NORM_DATETIME_PATTERN));
            }
            System.out.println("输出证书信息:\n" + certificate.toString());
            // 输出关键信息，截取部分并进行标记
            System.out.println("证书序列号:" + certificate.getSerialNumber().toString(16));
            System.out.println("版本号:" + certificate.getVersion());
            System.out.println("签发者：" + certificate.getIssuerDN());
            System.out.println("有效起始日期：" + certificate.getNotBefore());
            System.out.println("有效终止日期：" + certificate.getNotAfter());
            System.out.println("主体名：" + certificate.getSubjectDN());
            System.out.println("签名算法：" + certificate.getSigAlgName());
            System.out.println("签名：" + certificate.getSignature().toString());
        }
        System.out.println("serialNo:" + serialNo);
        return serialNo;
    }

    public String nativePay(ProductOrder order) {
        ProductType pt = productTypeService.selectProductTypeByProductCode(order.getProductCode());
        if (pt == null)
        {
            throw new ServiceException(StringUtils.format("产品标识({})非法。 ", order.getProductCode()));
        }

        ProductPrice price = productPriceService.selectProductPriceByPriceId(order.getPriceId());
        if (price == null)
        {
            throw new ServiceException(StringUtils.format("套餐标识({})非法。 ", order.getProductCode()));
        }
        try {
            String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3);
            UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel()
                    .setAppid(wxPayV3Bean.getAppId())
                    .setMchid(wxPayV3Bean.getMchId())
                    .setDescription(pt.getProductName())
                    .setOut_trade_no(PayKit.generateStr())
                    .setTime_expire(timeExpire)
                    .setAttach(order.getOrderNumber())
                    .setNotify_url(wxPayV3Bean.getDomain().concat("/v3/payNotify"))
                    .setAmount(new Amount().setTotal(price.getPrice().intValue()));

            log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel));
            IJPayHttpResponse response = WxPayApi.v3(
                    RequestMethod.POST,
                    WxDomainEnum.CHINA.toString(),
                    BasePayApiEnum.NATIVE_PAY.toString(),
                    wxPayV3Bean.getMchId(),
                    getSerialNumber(),
                    null,
                    wxPayV3Bean.getKeyPath(),
                    JSONUtil.toJsonStr(unifiedOrderModel)
            );
            log.info("统一下单响应 {}", response);
            // 根据证书序列号查询对应的证书来验证签名结果
            boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath());
            log.info("verifySignature: {}", verifySignature);

            String body = response.getBody();
            JSONObject paramsObj = JSON.parseObject(body);
            String codeUrl = paramsObj.getString("code_url");
            if (StringUtils.isEmpty(codeUrl))
            {
                throw new ServiceException("获取二维码失败，绝不可能");
            }
//            order.setQrCodeUrl(codeUrl);
//            productOrderService.updateProductOrder(order);
            return codeUrl;
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
    }

}
